<?php

/**
 * Clase principal para administrar vistas y sus funcionalidades
 * @author Robert Babilonia <bobbabilon2@gmail.com>
 * @todo Intentar implementar las vistas como clases, que hereden de esta clase principal, para garantizar la POO al 100%
 */
class CommanderView {

    /**
     * @var string $buffer Almacena la posible salida previa del buffer, la generada en los controladores o modelos
     */
    public static $buffer;

    /**
     * @var string Almacena la informacion de la vista a renderizar
     */
    private static $view;

    /**
     * @var array alamacena las variables recibidas desde el controlador
     */
    private static $vars = array();

    /**
     * Renderiza un partial en la vista donde es solicitado, busca previamente 
     * en el modulo especificado o por defecto y luego en el directorio de partials global,
     * si el partial no es encontrado se lanza una excepcion y la vista no es renderizada
     * @param string $partialName Nombre del partial que se requiere
     * @param array $vars Arreglo asociativo con los parametros a pasar al partial
     * @throws CommanderException
     */
    public static function partial($partialName, $vars = array()) {

        if (CommanderSession::exist("module")) {

            if ($vars && is_array($vars)) {

                //extrae los elementos de un arreglo asociativo para transformarlas en variables
                extract($vars);
            }
            $module = CommanderSession::get('module');
            $partial_file = MODULE_PATH . $module . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR . '__partials' . DIRECTORY_SEPARATOR . $partialName . '.php';

            // se verifica la existencia del partial solicitado en el modulo especifico
            if (is_file($partial_file)) {

                require $partial_file;
            } else {

                $partial_file = VIEWS_PATH . '__partials' . DIRECTORY_SEPARATOR . $partialName . '.php';

                // se verifica la existencia dela partial solicitado en el directorio global de partials
                if (is_file($partial_file)) {

                    require $partial_file;
                } else {

                    throw new CommanderException(ERROR_PARTIAL_NOT_FOUND . " " . $partialName);
                }
            }
        } else {

            throw new CommanderException(ERROR_MODULE_NOT_SET2 . $partialName);
        }
    }

    /**
     * Renderiza la vista solicitada, si la misma no es encontrada lanza una excepcion
     * @param string $controller
     * @param string $module
     * @param string $template
     * @param string $view
     * @param array $vars
     * @throws CommanderException
     *
     */
    public static function render($controller, $module = NULL, $template = "default", $view = "", $vars = array()) {

        
        if ($vars && is_array($vars)) {

            //extrae los elementos de un arreglo asociativo para transformarlas en variables
            self::$vars = $vars;
            extract($vars);
        }


        if ($template != AJAX_VIEW_DIR) {// si el renderizado es a una vista especifica
            $template_file = VIEWS_PATH . '__templates' . DIRECTORY_SEPARATOR . $template . '.php';
            $view_file = MODULE_PATH . $module . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR . $controller . DIRECTORY_SEPARATOR . $view . '.php';
        } else {

            $template_file = NULL;
            $view_file = VIEWS_PATH . AJAX_VIEW_DIR . DIRECTORY_SEPARATOR . $view . '.php';
        }

        // se verifica la existencia de la vista solicitada
        if (is_file($view_file)) {


            //se almacena la posible salida previa del buffer

            self::$buffer = ob_get_clean();

            //se limpia el buffer y se inicia el manejo de este

            ob_clean();
            ob_start();

            //se verifica si se va a mostrar el grid de blueprint o no

            if (CommanderApp::get_config('VIEW_DESIGNER_MODE')) {

                $show_grid = 'showgrid';
            } else {

                $show_grid = '';
            }

            //se verifica el template a usar    

            if (isset($template_file)) {
                // se mantiene la ruta de la vista a renderizar
                self::$view = $view_file;
                if (is_file($template_file)) {

                    require $template_file;
                } else {
                    //se usa un template por defecto si no existe el template solicitado
                    require VIEWS_PATH . '__templates/default.php';
                }
            } else {

                require $view_file;
            }
            // se envia la salida al buffer
            ob_end_flush();
        } else {

            throw new CommanderException(ERROR_VIEW_NOT_FOUND . " " . $view_file);
        }
    }

    /**
     * Carga el contendo de una vista
     * @throws CommanderException
     */
    public static function view_container() {

        if (is_file(self::$view)) {


            if (self::$vars && is_array(self::$vars)) {


                extract(self::$vars);
            }

            require self::$view;
        } else {

            throw new CommanderException(ERROR_VIEW_NOT_FOUND . " " . $view);
        }
    }

    /**
     * Genera el contenido principal del header para el correcto funcionamiento del frame
     * Hace inclusion de CSS y JS que son necesarios.
     */
    public static function header_container() {


        /**
         * Se incluyen las hojas de estilo del framework css blueprint
         */
        $cadena = CommanderView::stylesheet_link('blueprint/screen', array('media' => 'screen, projection'));
        $cadena.= CommanderView::stylesheet_link('blueprint/print', array('media' => 'print'));
        $cadena.= CommanderView::stylesheet_ie_link('blueprint/ie', array('media' => 'screen, projection'));
//$cadena.= CommanderView::stylesheet_link('blueprint/plugins/liquid/liquid', 'media="screen, projection"');
        $cadena.= CommanderView::stylesheet_link('blueprint/plugins/fancy-type/screen', array('media' => 'screen, projection'));
        $cadena.= CommanderView::stylesheet_link('blueprint/plugins/link-icons/screen', array('media' => 'screen, projection'));
        $cadena.= CommanderView::stylesheet_link('blueprint/plugins/buttons/screen', array('media' => 'screen, projection'));
        $cadena.= CommanderView::stylesheet_link('blueprint/plugins/sprites/sprite', array('media' => 'screen, projection'));

//fin blueprint css framework

        $cadena.= CommanderView::stylesheet_link('dataGrid/demo_page');
        $cadena.= CommanderView::stylesheet_link('dataGrid/demo_table');
        $cadena.= CommanderView::stylesheet_link('dataGrid/demo_table_jui');
//$cadena.= CommanderView::stylesheet_link('ui/custom/jquery-ui-1.8.19.custom.all');
        $cadena.= CommanderView::stylesheet_link('ui/azul/jquery-ui-1.8.15.custom');
        $cadena.= CommanderView::stylesheet_link('simple_modal/basic');
        $cadena.= CommanderView::stylesheet_link('notify/style');

        $cadena.= CommanderView::javascript_link('jquery/jquery');
        $cadena.= CommanderView::javascript_link('validate/jquery.metadata');
        $cadena.= CommanderView::javascript_link('validate/jquery.validate');
        $cadena.= CommanderView::javascript_link('dataGrid/jquery.dataTables_1_8_2');
        $cadena.= CommanderView::javascript_link('ui/custom/jquery-ui-1.8.19.custom.min');
        $cadena.= CommanderView::javascript_link('ui/custom/jquery.ui.widget');
        $cadena.= CommanderView::javascript_link('ui/custom/jquery.ui.core');
        $cadena.= CommanderView::javascript_link('ui/custom/jquery.ui.mouse');
        $cadena.= CommanderView::javascript_link('ui/custom/jquery.ui.datepicker');
        $cadena.= CommanderView::javascript_link('ui/custom/i18n/jquery.ui.datepicker-es');
        $cadena.= CommanderView::javascript_link('ui/custom/jquery.ui.slider');
        $cadena.= CommanderView::javascript_link('ui/custom/jquery.ui.tabs');
        $cadena.= CommanderView::javascript_link('ui/custom/jquery.ui.resizable');
        $cadena.= CommanderView::javascript_link('ui/custom/jquery.ui.draggable');
        $cadena.= CommanderView::javascript_link('ui/custom/jquery.ui.position');
        $cadena.= CommanderView::javascript_link('ui/custom/jquery.ui.dialog');
        $cadena.= CommanderView::javascript_link('notify/noty');
        $cadena.= CommanderView::javascript_link('notify/notify');

        /**
         * Declaracion de constantes javascritp para hacerlas disponibles a lo largo de
         * las vistas del frame.
         */
        $cadena.="<script type='text/javascript'> ";
        /**
         * Permite construir facilmente las peticiones ajax al servidor
         */
        $cadena.=" const BASIC_URL_PATH='" . BASIC_URL_PATH . "'; ";
        /**
         * Tiempo de duracion de las notificaciones javascript
         */
        $cadena.=" const JS_NOTIFICATION_TIME='" . JS_NOTIFICATION_TIME . "'; ";
        /**
         * Acceso al directorio public del servidor
         */
        $cadena.=" const PUBLIC_PATH='" . PUBLIC_PATH . "'; ";
        /**
         * Controlador usado para enviar la informacion del usuario si el modo SECURE_USER_BUGS esta activado
         */
        $cadena.=" const SESSION_INFO_CONTROLLER='" . CommanderApp::get_config('DEFAULT_CONTROLLER_REQUEST') . "'; ";
        $cadena.="</script>";

        if (CommanderApp::get_config('SECURE_USER_BUGS')) {

            $cadena.=CommanderView::javascript_link('commander/user_info');
        }

        echo $cadena;
    }

    /**
     * Genera el link de acceso a una hoja de estilo CSS
     * @param string $css_link
     * @param array $callback Asociativo tipo nombre=>valor, Permite agregar cualquier parametro especial al link resultante
     * @return string Cadena con etiquetas html para inclusion de css
     */
    public static function stylesheet_link($css_link, $callback = NULL) {


        $xml = new XMLWriter();
        $xml->openMemory();
        $xml->startElement('link');
        $xml->writeAttribute('href', CSS_PATH . $css_link . '.css');
        $xml->writeAttribute('rel', 'stylesheet');
        $xml->writeAttribute('type', 'text/css');

        if (is_array($callback)) {
            foreach ($callback as $key => $val) {

                $xml->writeAttribute($key, $val);
            }
        }

        $xml->endElement(); //fin del link
        $link = $xml->outputMemory();
        return $link;
    }

    /**
     * Genera link condicional para incluir CSS alternativo para los terribles navegadores de Microsoft
     * @param string $css_link
     * @param array $callback Asociativo tipo nombre=>valor, Permite agregar cualquier parametro especial al link resultante
     * @return string Cadena con etiquetas html para inclusion de css
     */
    public static function stylesheet_ie_link($css_link, $callback = NULL) {


        $xml = new XMLWriter();
        $xml->openMemory();
        $xml->writeRaw('<!--[if lt IE 8]>'); //comentarios condicionales para IE
        $xml->startElement('link');
        $xml->writeAttribute('href', CSS_PATH . $css_link . '.css');
        $xml->writeAttribute('rel', 'stylesheet');
        $xml->writeAttribute('type', 'text/css');

        if (is_array($callback)) {
            foreach ($callback as $key => $val) {

                $xml->writeAttribute($key, $val);
            }
        }

        $xml->endElement(); //fin del link
        $xml->writeRaw('<![endif]-->'); //fin comentarios para IE
        $link = $xml->outputMemory();

        return $link;
    }

    /**
     * Genera las etiquetas de inclusion de un archivo javasript
     * @param type $js_link
     * @param string $callback Permite agregar cualquier parametro especial al link resultante
     * @return string Cadena con etiquetas html para inclusion de js
     */
    public static function javascript_link($js_link, $callback = '') {

        $link = '<script type="text/javascript" src="' . JS_PATH . $js_link . '.js" ' . $callback . ' ></script>';
        return $link;
    }

    /**
     * Genera las etiquetas html para la inclusion de una imagen
     * @param string $img_link Link de la imagen a incluir, esta debe estar en public/images
     * @param string $alt_msj Mensaje a mostrar en caso de que no sea posible cargar la imagen
     * @param array $callback Arreglo nombre=>valor, con cualquier otro atributo para la etiqueta, como CSS, JS, etc.
     * @return string
     */
    public static function img_link($img_link, $alt_msj = '', $callback = NULL) {


        $xml = new XMLWriter();
        $xml->openMemory();
        $xml->startElement('img');
        $xml->writeAttribute('src', IMAGE_PATH . $img_link);
        $xml->writeAttribute('alt', $alt_msj);
        $xml->writeAttribute('title', $alt_msj);

        if (is_array($callback)) {
            foreach ($callback as $key => $val) {

                $xml->writeAttribute($key, $val);
            }
        }

        $xml->endElement(); //fin del img
        $link = $xml->outputMemory();
        return $link;
    }

    /**
     * Genera las etiquetas html para la inclusion de un enlace
     * @param string $a_link Direccion del enlace, debe ser una direccion absoluta o relativa, segun se requiera
     * @param string $value Mensaje a mostrar en el enlace
     * @param array $callback Arreglo nombre=>valor, con cualquier otro atributo para la etiqueta, como CSS, JS, etc.
     * @return string
     */
    public static function anchor_link($a_link, $value = '', $callback = NULL) {


        $xml = new XMLWriter();
        $xml->openMemory();
        $xml->startElement('a');
        $xml->writeAttribute('href', $a_link);


        if (is_array($callback)) {
            foreach ($callback as $key => $val) {

                $xml->writeAttribute($key, $val);
            }
        }
        $xml->writeRaw($value);
        $xml->endElement(); //fin del img
        $link = $xml->outputMemory();
        return $link;
    }

    /**
     * Genera las etiquetas html para la peticion a la accion de un controlador en el frame, 
     * @param string $a_link Direccion del enlace, si el modo Modular no esta activado recibe la forma : nombrecontrolador/metodo/parametro1/parametroN
     * si el modo modular esta activado recibe: modulo/nombrecontrolador/metodo/parametro1/parametroN
     * @param string $value Mensaje a mostrar en el enlace
     * @param array $callback Arreglo nombre=>valor, con cualquier otro atributo para la etiqueta, como CSS, JS, etc.
     * @return string
     */
    public static function anchor_action_link($a_link, $value = '', $callback = NULL) {


        return self::anchor_link(BASIC_URL_PATH . '/' . $a_link, $value, $callback);
    }

    /**
     * Construye un boton del tipo submit
     * @param string $value Mensaje del boton a ser generado
     * @param string $callback Arreglo del tipo nombre=>valor de los atributos que se quieren agregar al boton
     * @return string
     */
    public static function button_submit($value, $callback = array()) {

        return self::button_custom($value, 'positive', $callback, 'submit');
    }

    /**
     * Construye un boton del tipo reset
     * @param string $value Mensaje del boton a ser generado
     * @param string $callback Arreglo del tipo nombre=>valor de los atributos que se quieren agregar al boton
     * @return string
     */
    public static function button_reset($value, $callback = array()) {

        return self::button_custom($value, 'negative', $callback, 'reset');
    }

    /**
     * Construye un boton del tipo deseado: negative, positive, process
     * @param string $value Mensaje del boton a ser generado
     * @param string $custom_class Especifica la imagen asociada a un boton, valores permitidos: negative, positive, process
     * @param string $callback Arreglo del tipo nombre=>valor de los atributos que se quieren agregar al boton
     * @param string $type Indica el tipo de boton a construir: button, submit, reset
     * @return string
     */
    public static function button_custom($value, $custom_class = 'process', $callback = array(), $type = 'button') {

        $btn['class'] = array('negative' => 'negative', 'positive' => 'positive', 'process' => '');
        $btn['img'] = array('negative' => 'unavailable.png', 'positive' => 'available.png', 'process' => 'widget.png');

        if (!isset($btn['class'][$custom_class])) {
            $custom_class = 'process';
        }

        $xml = new XMLWriter();
        $xml->openMemory();
        $xml->startElement('button');

        if (is_array($callback)) {

            foreach ($callback as $key => $val) {

                $val = str_replace('"', "'", $val);
                $xml->writeAttribute($key, $val);
            }
        }
        $xml->writeAttribute('type', $type);
        $xml->writeAttribute('class', 'button ' . $btn['class'][$custom_class]);
        $xml->startElement('img');
        $xml->writeAttribute('src', IMAGE_PATH . 'commander/' . $btn['img'][$custom_class]);
        $xml->endElement(); //fin del img
        $xml->writeRaw($value); // texto del boton
        $xml->endElement(); //fin del button
        $button = $xml->outputMemory();
        return $button;
    }
    
    
    
     /**
      * Construye un combo select
      * @param string $name Identificador name del combo
      * @param array $values Arreglo asociativo de la forma 'texto' => 'valor'
      * @param string $selected Indica el value del elemento que se quiere tener seleccionado por defecto
      * @param string $callback Arreglo del tipo nombre=>valor de los atributos que se quieren agregar al boton
      * @return string
      */
    public static function imput_select($name, $values = array(), $selected='', $callback = NULL) {

        $xml = new XMLWriter();
        $xml->openMemory();
        $xml->startElement('select');
        $xml->writeAttribute('name', $name);


        if (is_array($callback)) {
            foreach ($callback as $key => $val) {

                $xml->writeAttribute($key, $val);
            }
        }
        
        if(is_array($values)){
            foreach ($values as $text => $value) {
                
                $xml->startElement('option');
                if($selected==$value){
                    
                    $xml->writeAttribute("selected", 'selected');
                }
                
                
                $xml->writeAttribute("value", $value);
                $xml->writeRaw($text);
                
                $xml->endElement(); //fin del option
                
            }

        }        
        
        //$xml->writeRaw($value);
        $xml->endElement(); //fin del select
        $link = $xml->outputMemory();
        return $link;
    }

}

?>